﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Audio;

namespace WindowsGame1.View
{
    class GameView
    {
        //nivå-tiles
        private Texture2D       _levelTexture;
        private Texture2D       _background1;
        
        //spelarens tiles
        private Texture2D       _healthbar;
        private Texture2D       _playerRightTexture;
        private Texture2D       _playerLeftTexture;

        //fiende-tiles
        private Texture2D       _enemyTexture;
        private Texture2D       _mineTexture;
        private Texture2D       _enemyStalker;

        //particle-tiles
        private Texture2D       _stars;

        //övrigt
        private Texture2D       _carrotTexture;
        private SpriteFont      _font;
        private SpriteBatch     _spriteBatch;
        private KeyboardState   _oldKeyboardState;
        
        //note that the view scale is less than texture scale
        private int             _textureTileSize = 64;

        GameState               _state = GameState.Playing;
        PlayerState             _playerState = PlayerState.Right;

        private enum GameState
        {
            Playing,
            Level_Complete,
            Player_Died,
            Game_Complete,
            Game_Over
        }

        private enum PlayerState
        {
            Left,
            Right
        }

        //Partikelsystem
        private FireworksSystem _fireworks = new FireworksSystem();

        //Konstruktor
        public GameView(GraphicsDeviceManager a_manager, ContentManager a_contentManager)
        {
            _spriteBatch = new SpriteBatch(a_manager.GraphicsDevice);
            _playerRightTexture = a_contentManager.Load<Texture2D>("easterbunnyRight");
            _playerLeftTexture = a_contentManager.Load<Texture2D>("easterbunnyLeft");
            _levelTexture = a_contentManager.Load<Texture2D>("tiles3");
            _healthbar = a_contentManager.Load<Texture2D>("HealthBar");
            _font = a_contentManager.Load<SpriteFont>("SpriteFont1");
            _stars = a_contentManager.Load<Texture2D>("stars");
            _enemyTexture = a_contentManager.Load<Texture2D>("enemyLeft");
            _carrotTexture = a_contentManager.Load<Texture2D>("carrot");
            _background1 = a_contentManager.Load<Texture2D>("Background01");
            _mineTexture = a_contentManager.Load<Texture2D>("EnemyMine");
            _enemyStalker = a_contentManager.Load<Texture2D>("enemyRight");
        }

        //Huvudmetod föt att rita ut spelet
        internal void DrawGame(GraphicsDevice a_graphicsDevice, Model.Level a_level, Camera a_camera, List<Vector2> enemyPositions, List<Vector2> enemyMinePositions, List<Vector2> carrotPositions,
                               Vector2 a_modelPlayerPosition, List<Vector2> stalkerPosition, int a_currentHealth, float a_elapsedTime)
        {

            //Positionering
            Vector2 viewportSize = new Vector2(a_graphicsDevice.Viewport.Width, a_graphicsDevice.Viewport.Height);
            float scale = a_camera.GetScale();
            Vector2 centerScreenPosition = new Vector2(viewportSize.X / 2, viewportSize.Y / 2);

            a_graphicsDevice.Clear(Microsoft.Xna.Framework.Color.White);

            _spriteBatch.Begin();

            //Background
            DrawBackground(a_graphicsDevice, viewportSize);

            //draw level
            for (int x = 0; x < Model.Level.g_levelWidth; x++)
            {
                for (int y = 0; y < Model.Level.g_levelHeight; y++)
                {
                    Vector2 viewPos = a_camera.GetViewPosition(x, y, viewportSize);
                    DrawTile(viewPos.X, viewPos.Y, scale, a_level._tiles[x, y]);
                }
            }

            Vector2 playerViewPos = a_camera.GetViewPosition(a_modelPlayerPosition.X, a_modelPlayerPosition.Y, viewportSize);
            
            //Healthbar
            DrawHealthbar(a_currentHealth);

            /**
             * States beroende på hur de går i spelet
             */
            //GameOver
            if (_state == GameState.Game_Over)
            {
                string text1 = "GAME OVER!";
                string text2 = "The enemy reached the basket first!";
                string text3 = "Press Esc to exit!";
                _spriteBatch.DrawString(_font, text1, new Vector2(a_graphicsDevice.Viewport.Width / 2 - 60, a_graphicsDevice.Viewport.Height / 2 - 40), Color.Red);
                _spriteBatch.DrawString(_font, text2, new Vector2(a_graphicsDevice.Viewport.Width / 2 - 80, a_graphicsDevice.Viewport.Height / 2), Color.Red);
                _spriteBatch.DrawString(_font, text3, new Vector2(a_graphicsDevice.Viewport.Width / 2 - 60, a_graphicsDevice.Viewport.Height / 2 + 40), Color.Red);
            }
            else
            {
                //Game was complete
                if (_state == GameState.Game_Complete)
                {
                    string text1 = "You won the Game!";
                    string text2 = "Press Esc to exit!";
                    _spriteBatch.DrawString(_font, text1, new Vector2(a_graphicsDevice.Viewport.Width / 2 - 60, a_graphicsDevice.Viewport.Height / 2 - 40), Color.Green);
                    _spriteBatch.DrawString(_font, text2, new Vector2(a_graphicsDevice.Viewport.Width / 2 - 60, a_graphicsDevice.Viewport.Height / 2), Color.Green);
                    _fireworks.Draw(_spriteBatch, _stars, a_elapsedTime);
                }
                else
                {
                    //Player won level
                    if (_state == GameState.Level_Complete)
                    {
                        string text1 = "You won the level!";
                        string text2 = "Press Enter to get to the next level!";
                        _spriteBatch.DrawString(_font, text1, new Vector2(a_graphicsDevice.Viewport.Width / 2 - 60, a_graphicsDevice.Viewport.Height / 2 - 40), Color.Red);
                        _spriteBatch.DrawString(_font, text2, new Vector2(a_graphicsDevice.Viewport.Width / 2 - 60, a_graphicsDevice.Viewport.Height / 2), Color.Red);
                        _fireworks.Draw(_spriteBatch, _stars, a_elapsedTime);
                    }

                    //Player has died
                    if (_state == GameState.Player_Died)
                    {
                        string text1 = "GAME OVER";
                        string text2 = "Press Esc to quit!";
                        _spriteBatch.DrawString(_font, text1, new Vector2(a_graphicsDevice.Viewport.Width / 2 - 60, a_graphicsDevice.Viewport.Height / 2 - 40), Color.Red);
                        _spriteBatch.DrawString(_font, text2, new Vector2(a_graphicsDevice.Viewport.Width / 2 - 60, a_graphicsDevice.Viewport.Height / 2), Color.Red);
                    }
                }
            }

            //Enemy
            foreach (Vector2 a in enemyPositions)
            {
                Vector2 enemyViewPosition = a_camera.GetViewPosition(a.X, a.Y, viewportSize);
                DrawEnemyAt(enemyViewPosition, scale);
            }

            //Enemy-mine
            foreach (Vector2 b in enemyMinePositions)
            {
                Vector2 enemyMineViewPosition = a_camera.GetViewPosition(b.X, b.Y, viewportSize);
                DrawEnemyMineAt(enemyMineViewPosition, scale);
                
            }

            //carrot
            foreach (Vector2 b in carrotPositions)
            {
                Vector2 carrotViewPosition = a_camera.GetViewPosition(b.X, b.Y, viewportSize);
                DrawCarrotAt(carrotViewPosition, scale);
            }

            //stalker
            foreach (Vector2 b in stalkerPosition)
            {
                Vector2 stalkerPositionView = a_camera.GetViewPosition(b.X, b.Y, viewportSize);
                DrawStalkerAt(stalkerPositionView, scale);
            }

            //player
            DrawPlayerAt(playerViewPos, scale);
            _spriteBatch.End();
        }

        //Metod för att ändra spelens status till spelande
        public void StartPlayingLevel()
        {
            _state = GameState.Playing;
        }

        //Metod för att rita ut bakgrunden
        private void DrawBackground(GraphicsDevice a_graphicsDevice, Vector2 a_centerPosition)
        {
            int screenWidth = a_graphicsDevice.PresentationParameters.BackBufferWidth;
            int screenHeight = a_graphicsDevice.PresentationParameters.BackBufferHeight;
            Rectangle screenRectangle = new Rectangle(0, 0, screenWidth, screenHeight);
            _spriteBatch.Draw(_background1, screenRectangle, Color.White);
        }
        
        //Metod för att rita ut healthbaren
        private void DrawHealthbar(int a_currentHealth)
        {
            //healthbar


            //draw the current health
            _spriteBatch.Draw(_healthbar, new Rectangle(_healthbar.Width / 2 - 200,

                  30, _healthbar.Width, 44), new Rectangle(0, 45, _healthbar.Width, 44), Color.Gray);

            //Draw the current health level based on the current Health
            _spriteBatch.Draw(_healthbar, new Rectangle(_healthbar.Width / 2 - 200,
                 30, (int)(_healthbar.Width * ((double)a_currentHealth / 100)), 44),
                 new Rectangle(0, 45, _healthbar.Width, 44), Color.Red);

            //draw the box around the healthbar
            _spriteBatch.Draw(_healthbar, new Rectangle(_healthbar.Width / 2 - 200,
                  30, _healthbar.Width, 44), new Rectangle(0, 0, _healthbar.Width, 44), Color.White);
        }
        
        //Metod för att rita ut spelaren
        private void DrawPlayerAt(Microsoft.Xna.Framework.Vector2 a_viewBottomCenterPosition, float a_scale)
        {
            //ritar ut karaktären beroende på om spelaren är riktad till vänster eller höger
            if (_playerState == PlayerState.Right)
            {
                //Create rectangle and draw it, note the transformation of the position
                Rectangle destRect = new Rectangle((int)(a_viewBottomCenterPosition.X - a_scale / 2.0f), (int)(a_viewBottomCenterPosition.Y - a_scale), (int)a_scale, (int)a_scale);
                _spriteBatch.Draw(_playerRightTexture, destRect, Color.White);
            }
            else
            {
                Rectangle destRect = new Rectangle((int)(a_viewBottomCenterPosition.X - a_scale / 2.0f), (int)(a_viewBottomCenterPosition.Y - a_scale), (int)a_scale, (int)a_scale);
                _spriteBatch.Draw(_playerLeftTexture, destRect, Color.White);
            }
        }
        
        //Metod för att måla ut "tiles"
        private void DrawTile(float a_x, float a_y, float a_scale, Model.Tile a_tile)
        {

            //Get the source rectangle (pixels on the texture) for the tile type 
            Rectangle sourceRectangle = new Rectangle(_textureTileSize * (int)a_tile._tileType, 0, _textureTileSize, _textureTileSize);

            //Destination rectangle in windows coordinates only scaling
            Rectangle destRect = new Rectangle((int)a_x, (int)a_y, (int)a_scale, (int)a_scale);

            //gör så att "onödiga positioner" inte syns
            if (a_tile._tileType != Model.Tile.TileType.T_EMPTY)
            {
                if (a_tile._tileType != Model.Tile.TileType.T_CHICKEN_SPAWN_POSITION)
                {
                    if (a_tile._tileType != Model.Tile.TileType.T_CARROT_POSITION)
                    {
                        if (a_tile._tileType != Model.Tile.TileType.T_MINE_SPAWN_POSITION)
                        {
                            if (a_tile._tileType != Model.Tile.TileType.T_STALKING_CHICKEN_SPAWN)
                            {
                                _spriteBatch.Draw(_levelTexture, destRect, sourceRectangle, Color.White);
                            }
                        }
                    }
                }
                
            }
        }

        //Metod för att måla ut fienden
        private void DrawEnemyAt(Microsoft.Xna.Framework.Vector2 a_viewBottomCenterPosition, float a_scale)
        {
            Rectangle destination = new Rectangle((int)(a_viewBottomCenterPosition.X - a_scale / 2.0f), (int)(a_viewBottomCenterPosition.Y - a_scale), (int)a_scale, (int)a_scale);

            _spriteBatch.Draw(_enemyTexture, destination, Color.White);
        }

        //Metod för att måla ut fiende-minorna
        private void DrawEnemyMineAt(Microsoft.Xna.Framework.Vector2 a_viewBottomCenterPosition, float a_scale)
        {
            Rectangle destination = new Rectangle((int)(a_viewBottomCenterPosition.X - a_scale / 32), (int)(a_viewBottomCenterPosition.Y), (int)a_scale, (int)a_scale);

            _spriteBatch.Draw(_mineTexture, destination, Color.White);
        }

        //Metod för att rita ut morötterna
        private void DrawCarrotAt(Microsoft.Xna.Framework.Vector2 a_viewBottomCenterPosition, float a_scale)
        {
            Rectangle destination = new Rectangle((int)(a_viewBottomCenterPosition.X - a_scale / 2.0f), (int)(a_viewBottomCenterPosition.Y - a_scale), (int)a_scale, (int)a_scale);

            _spriteBatch.Draw(_carrotTexture, destination, Color.White);
        }

        //Metod för att rita upp "stalkern"
        private void DrawStalkerAt(Microsoft.Xna.Framework.Vector2 a_viewBottomCenterPosition, float a_scale)
        {
            Rectangle destination = new Rectangle((int)(a_viewBottomCenterPosition.X - a_scale / 2.0f), (int)(a_viewBottomCenterPosition.Y), (int)a_scale, (int)a_scale);

            _spriteBatch.Draw(_enemyStalker, destination, Color.White);
        }

        //Ställer in att man har klarat av spelet
        public void PlayerWonGame()
        {
            _state = GameState.Game_Complete;
        }

        //Ställer in att man har vunnit nivån
        public void PlayerWonLevel()
        {
            _state = GameState.Level_Complete;
        }

        //Ställer in att man har förlorat spelet
        public void GameOver()
        {
            _state = GameState.Game_Over;
        }

        //Ställer in att spelaren har dött
        public void PlayerDied()
        {
            _state = GameState.Player_Died;
        }

        //metod för att vända spelaren höger
        public void TurnPlayerRight()
        {
            _playerState = PlayerState.Right;
        }

        //metod för att vända spelaren vänster
        public void TurnPlayerLeft()
        {
            _playerState = PlayerState.Left;
        }

        /**
         * Moving
         */ 
        public bool DidPlayerPressJump()
        {
            Keys jumpKey = Keys.Up;

            KeyboardState newState = Keyboard.GetState();

            //save state
            _oldKeyboardState = newState;


            //has been pressed and released
            if (_oldKeyboardState.IsKeyDown(jumpKey))
            {
                return true;
            }
            return false;
        }

        public bool DidPlayerPressRight()
        {
            return _oldKeyboardState.IsKeyDown(Keys.Right);
        }

        public bool DidPlayerPressLeft()
        {
            return _oldKeyboardState.IsKeyDown(Keys.Left);
        }

        public bool DidPlayerPressEsc()
        {
            return _oldKeyboardState.IsKeyDown(Keys.Escape);
        }

        public bool DidPlayerPressEnter()
        {
            return _oldKeyboardState.IsKeyDown(Keys.Enter);
        }

        public bool StopVelocity()
        {
            if(_oldKeyboardState.IsKeyUp(Keys.Right) == true &&
                _oldKeyboardState.IsKeyUp(Keys.Left) == true)
            {
                return true;
            }
            return false;
        }

    }
}
